<template>
  <div
    draggable="true"
    :class="['design-frame-wrapper', { active: showOperation }]"
    :style="frameStyle"
    @dragstart="drag"
    @click.stop="setActiveComponent"
  >
    <slot></slot>

    <ul class="operation-box" v-show="showOperation">
      <li class="text-update">
        <el-input v-model="textSubjectForm.text"></el-input>
      </li>
      <li
        class="operation-item lt"
        @mousedown="(ev) => handleMouseDown(ev, 'left top')"
      ></li>
      <li
        class="operation-item lc"
        @mousedown="(ev) => handleMouseDown(ev, 'left center')"
      ></li>
      <li
        class="operation-item lb"
        @mousedown="(ev) => handleMouseDown(ev, 'left bottom')"
      ></li>
      <li
        class="operation-item ct"
        @mousedown="(ev) => handleMouseDown(ev, 'center top')"
      ></li>
      <li
        class="operation-item cb"
        @mousedown="(ev) => handleMouseDown(ev, 'center bottom')"
      ></li>
      <li
        class="operation-item rt"
        @mousedown="(ev) => handleMouseDown(ev, 'right top')"
      ></li>
      <li
        class="operation-item rc"
        @mousedown="(ev) => handleMouseDown(ev, 'right center')"
      ></li>
      <li
        class="operation-item rb"
        @mousedown="(ev) => handleMouseDown(ev, 'right bottom')"
      ></li>
    </ul>
  </div>
</template>

<script lang="ts">
import { useMainStore } from "@/store";
import { computed, defineComponent, reactive, ref, onMounted } from "vue";
import { calculateStyle } from "@/util/style";
import { debounce } from "@/util/tool";

export default defineComponent({
  name: "DesignFrame",
  props: ["componentName", "componentParams", "viewCompoentName"],
  setup(props) {
    const store = useMainStore();

    const showOperation = computed(() => {
      return store.activeComponentName === props.componentName;
    });

    const { PositionForm, SizeForm } = props.componentParams;
    const frameStyle = computed(() => {
      const position = calculateStyle(PositionForm.property);
      const size = calculateStyle(SizeForm.property);

      return { ...position, ...size };
    });

    const setActiveComponent = () => {
      store.setActiveComponetName(props.componentName);
    };

    // 这种绑定事件，解除绑定事件牛皮
    const handleMouseDown = (ev: MouseEvent, direction: string) => {
      ev.preventDefault();
      ev.stopPropagation();

      // 这里需要复制一份，否则数值增长会过快，因为响应式数据SizeForm更新后参与计算
      const currentSizeForm = JSON.parse(JSON.stringify(SizeForm));
      const currentPositionForm = JSON.parse(JSON.stringify(PositionForm));

      let startX = ev.x;
      let startY = ev.y;

      const move = (e: MouseEvent) => {
        let x = e.x;
        let y = e.y;

        let disX = x - startX;
        let disY = y - startY;

        let positionForm: any = {};
        // 这段代码牛皮呀
        if (direction) {
          if (direction.indexOf("top") >= 0) {
            disY = 0 - disY;
            positionForm.top = currentPositionForm.property.top - disY;
          }

          if (direction.indexOf("left") >= 0) {
            disX = 0 - disX;
            positionForm.left = currentPositionForm.property.left - disX;
          }
        }

        // 大小相关的样式
        let sizeStyle = {
          width: Number(currentSizeForm.property.width) + disX,
          height: Number(currentSizeForm.property.height) + disY,
        };

        debounce(
          store.setComponentOptions(props.componentName, {
            SizeForm: sizeStyle,
            PositionForm: positionForm,
          })
        );
      };

      const up = () => {
        document.removeEventListener("mousemove", move);
        document.removeEventListener("mouseup", up);
        // 做一个历史记录的作用
        // this.context.recordCanvasChangeHistory();
      };

      document.addEventListener("mousemove", move);
      document.addEventListener("mouseup", up);
    };

    const drag = (event: DragEvent) => {
      const dataTransfer = event.dataTransfer as DataTransfer;
      let pageX = event.pageX;
      let pageY = event.pageY;
      const { PositionForm } = props.componentParams;
      dataTransfer.setData("componentName", props.componentName);
      dataTransfer.setData(
        "startPos",
        JSON.stringify({
          pageX,
          pageY,
          top: PositionForm.property.top,
          left: PositionForm.property.left,
        })
      );
      dataTransfer.setData("isMove", "true");
    };
    const textSubjectForm = reactive(
      props.componentParams[props.viewCompoentName + "Form"].subject
    );

    return {
      showOperation,
      frameStyle,
      setActiveComponent,
      handleMouseDown,
      drag,
      textSubjectForm,
    };
  },
});
</script>

<style lang="scss" scoped>
.design-frame-wrapper {
  display: inline-block;
  box-sizing: border-box;
  cursor: pointer;
  &.active {
    border: solid 1px rgba(0, 87, 255, 0.5) !important;
    cursor: all-scroll;
  }
}

.operation-box {
  .operation-item {
    position: absolute;
    left: -5px;
    top: -5px;
    width: 8px;
    height: 8px;
    background-color: rgba(0, 87, 255, 0.5);
    border-radius: 50%;
    cursor: se-resize;

    &.lc {
      top: 50%;
      cursor: w-resize;
      margin-top: -5px;
    }

    &.lb {
      top: auto;
      bottom: -5px;
      left: -5px;
      cursor: ne-resize;
    }

    &.ct {
      left: 50%;
      cursor: s-resize;
      margin-left: -5px;
    }

    &.cb {
      left: 50%;
      margin-left: -5px;
      margin-bottom: -5px;
      bottom: 0;
      cursor: s-resize;
      top: auto;
    }

    &.rt {
      right: 0;
      cursor: ne-resize;
      margin-right: -5px;
      left: auto;
    }

    &.rc {
      right: 0;
      top: 50%;
      left: auto;
      cursor: w-resize;
      margin-right: -5px;
      margin-top: -5px;
    }

    &.rb {
      left: auto;
      top: auto;
      bottom: -5px;
      right: -5px;
      cursor: se-resize;
    }
  }

  .text-update {
    position: absolute;
    top: -40px;
  }
}
</style>
